package com.atwisdom.star.core.dao.pojo.modelClass.resource;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.util.JsonUtil;
import com.atwisdom.star.common.util.ObjectMapperUtil;
import com.atwisdom.star.core.dao.pojo.modelClass.BaseInstance;
import com.atwisdom.star.core.dao.pojo.modelClass.logic.LogicInstance;
import com.atwisdom.star.core.dao.util.DaoUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.SneakyThrows;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;

import java.text.ParseException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 *
 * @TableName resource_instance
 */
@TableName(value ="resource_instance",autoResultMap = true)
@Data
public class ResourceInstance extends BaseInstance {
    @TableField(exist = false)
    private static final long serialVersionUID = 1L;

    public ResourceInstance(){

    }
    public JSONObject getInsJsonObject(ResourceModel resourceModel){
        JSONObject JsonObject = new JSONObject();
        JsonObject.put("id", this.id);
        JsonObject.put("type", this.type);
        JsonObject.put("name", this.name);
        JsonObject.put("className", this.className);
        JsonObject.put("version", version);
        JsonObject.put("web", this.web);
        JsonObject.put("others", this.others);
        JsonObject.put("locked", this.lock);
        JsonObject.put("published", this.published);
        JsonObject.put("comments", this.comments);
        JsonObject.put("deleteFlag", this.deleteFlag);
        JsonObject.put("createdBy", this.getCreatedBy());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        if (this.getCreateTime() != null) {
            JsonObject.put("createTime", this.getCreateTime().format(formatter));
        }
        JsonObject.put("updatedBy", this.getUpdatedBy());
        if (this.getUpdateTime() != null) {
            JsonObject.put("updateTime", this.getUpdateTime().format(formatter));
        }
        JSONObject values = this.getValues();
        if(values==null){
            values = new JSONObject();
        }
        JSONObject theJsonObject = JSONObject.parseObject(JSON.toJSONString(this));
        if(resourceModel.getProperties()!=null){
            List<JSONObject> featureProperties = resourceModel.fetchFeatureProperties();
            JSONObject finalValues = values;
            featureProperties.forEach(f -> {
                String name = f.getString("name");
                String code = f.getString("code");
                Object o = theJsonObject.get(code);
                finalValues.put(name, o);
            });

            JSONObject nonValues = resourceModel.fetchNonFeatureValues();
            for(String key:nonValues.keySet()){
                if(!values.keySet().contains(key)){
                    values.put(key,nonValues.get(key));
                }
            }
            JsonObject.put("values", values);
        }else{
            JsonObject.put("values", new JSONObject());
        }

        if(resourceModel.getStatusProperties()!=null){
            resourceModel.getStatusProperties().forEach(st->{
                JSONObject item = JSONObject.parseObject(JSON.toJSONString(st));
                String name = item.getString("name");
                String code = item.getString("code");
                Object o = theJsonObject.get(code);
                JsonObject.put(name,o);
            });
        }
        return JsonObject;
    }

    public JSONObject getInfoJsonObject(){
        JSONObject JsonObject = new JSONObject();
        JsonObject.put("id", this.id);
        JsonObject.put("type", this.type);
        JsonObject.put("name", this.name);
        JsonObject.put("className", this.className);
        JsonObject.put("version", version);
        JsonObject.put("others", this.others);
        JsonObject.put("published", this.published);
        JsonObject.put("comments", this.comments);
        JsonObject.put("createdBy", this.getCreatedBy());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        if (this.getCreateTime() != null) {
            JsonObject.put("createTime", this.getCreateTime().format(formatter));
        }
        JsonObject.put("updatedBy", this.getUpdatedBy());
        if (this.getUpdateTime() != null) {
            JsonObject.put("updateTime", this.getUpdateTime().format(formatter));
        }
        return JsonObject;
    }

    @SneakyThrows
    public ResourceInstance(ResourceModel resourceModel, JSONObject jsonObject){
        JSONObject allValues = jsonObject.getJSONObject("values");
        if(resourceModel.getProperties() != null){
            JSONObject nonFeatures = resourceModel.fetchNonFeatures();
            JSONObject nonValues = JsonUtil.merge(nonFeatures, allValues);
            List<JSONObject> featureProperties = resourceModel.fetchFeatureProperties();
            featureProperties.forEach(f->{
                String name = f.getString("name");
                String code = f.getString("code");
                Object defaultValue = f.get("defaultValue");
                if(allValues != null && allValues.containsKey(name)){
                    jsonObject.put(code,allValues.get(name));
                }else{
                    if (!jsonObject.containsKey("needDefaultValue") || jsonObject.getBoolean("needDefaultValue")) {
                        jsonObject.put(code, defaultValue);
                    } else {
                        jsonObject.put(code, null);
                    }
                }
            });
            if (nonValues != null) {
                Set<String> keys = nonValues.keySet();
                for (String name : keys) {
                    JSONObject nvObj = resourceModel.fetchPropertiesByName(name);
                    if (nvObj == null) {
                        continue;
                    }
                    String type = nvObj.getString("type");
                    String valuesStr = allValues.getString(name);
                    if(allValues!=null && !"string".equalsIgnoreCase(type) && StringUtils.isNotBlank(valuesStr)){
                        Object dataObject = DaoUtil.ConvertFieldData(valuesStr, type);
                        nonValues.put(name, dataObject);
                    }
                }
                jsonObject.put("values", nonValues);
            }
        }else{
            jsonObject.put("values",new JSONObject());
        }

        if(resourceModel.getStatusProperties() != null){
            resourceModel.getStatusProperties().forEach(st->{
                JSONObject item = JSONObject.parseObject(JSON.toJSONString(st));
                String code = item.getString("code");
                Object defaultValue = item.get("defaultValue");
                jsonObject.put(code,defaultValue);
            });
        }

        ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper();
        ResourceInstance instance = objectMapper.readValue(JSON.toJSONString(jsonObject), ResourceInstance.class);
        BeanUtils.copyProperties(instance,this);
    }

    public ResourceInstance(ResourceModel resourceModel, JSONObject jsonObject, JSONObject sourceValues) {
        if(resourceModel.getProperties()!=null){
            JSONObject allValues =jsonObject.getJSONObject("values");
            JSONObject nonFeatures = resourceModel.fetchNonFeatures();
            nonFeatures = JsonUtil.merge(nonFeatures, sourceValues);
            JSONObject nonValues = JsonUtil.merge(nonFeatures, allValues);
            List<JSONObject> featureProperties = resourceModel.fetchFeatureProperties();
            featureProperties.forEach(f -> {
                String name = f.getString("name");
                String code = f.getString("code");
                Object defaultValue = f.get("defaultValue");
                if (allValues !=null && allValues.containsKey(name)) {
                    String type = f.getString("type");
                    Object dataObject = DaoUtil.ConvertFieldData(allValues.getString(name), type);
                    jsonObject.put(code, dataObject);
                } else if (sourceValues.containsKey(name)) {
                    jsonObject.put(code, sourceValues.get(name));
                } else {
                    if (!jsonObject.containsKey("needDefaultValue") || jsonObject.getBoolean("needDefaultValue")) {
                        jsonObject.put(code, defaultValue);
                    } else {
                        jsonObject.put(code, null);
                    }
                }
            });
            if (nonValues != null) {
                Set<String> keys = nonValues.keySet();
                for (String name : keys) {
                    JSONObject nvObj = resourceModel.fetchPropertiesByName(name);
                    if (nvObj == null) {
                        continue;
                    }
                    String type = nvObj.getString("type");
                    String valuesStr = allValues.getString(name);
                    if(allValues!=null && !"string".equalsIgnoreCase(type) && StringUtils.isNotBlank(valuesStr)){
                        Object dataObject = DaoUtil.ConvertFieldData(valuesStr, type);
                        nonValues.put(name, dataObject);
                    }
                }
                jsonObject.put("values", nonValues);
            }
        }else{
            jsonObject.put("values", new JSONObject());
        }

        if(resourceModel.getStatusProperties() != null){
            resourceModel.getStatusProperties().forEach(st->{
                JSONObject item = JSONObject.parseObject(JSON.toJSONString(st));
                String name = item.getString("name");
                String code = item.getString("code");
                Object o = jsonObject.get(name);
                jsonObject.put(code,o);
            });
        }

        ResourceInstance instance = JSONObject.parseObject(JSON.toJSONString(jsonObject), ResourceInstance.class);
        BeanUtils.copyProperties(instance, this);
    }

    /**
     * 获取摘要数据列
     * @return 反回查询列
     */
    public static String[] getSimpleColumns(){
        List<String> columns = new ArrayList<>();
        columns.add("id");
        columns.add("className");
        columns.add("type");
        columns.add("version");
        columns.add("others");
        columns.add("published");
        columns.add("updatedBy");
        columns.add("updateTime");
        columns.add("createdBy");
        columns.add("createTime");
        return columns.toArray(new String[0]);
    }
}
